if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = virq;
+ op.u.bind_virq.vcpu = cpu;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
evtchn = op.u.bind_virq.port;
if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == -1) {
op.cmd = EVTCHNOP_bind_ipi;
+ op.u.bind_ipi.vcpu = cpu;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
evtchn = op.u.bind_ipi.port;
/* Get a new binding from Xen. */
op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = virq;
+ op.u.bind_virq.vcpu = 0;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
evtchn = op.u.bind_virq.port;
/* Get a new binding from Xen. */
op.cmd = EVTCHNOP_bind_ipi;
+ op.u.bind_ipi.vcpu = 0;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
evtchn = op.u.bind_ipi.port;
op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = (u32)virq;
-
+ op.u.bind_virq.vcpu = 0;
+
if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
{
if ( port != NULL )
static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
{
struct evtchn *chn;
- struct vcpu *v = current;
- struct domain *d = v->domain;
+ struct vcpu *v;
+ struct domain *d = current->domain;
int port, virq = bind->virq;
if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
return -EINVAL;
- if ( d->domain_id == 0 && virq >= VIRQ_CONSOLE )
- v = d->vcpu[0];
+ if ( (v = d->vcpu[bind->vcpu]) == NULL )
+ return -ENOENT;
spin_lock(&d->evtchn_lock);
struct domain *d = current->domain;
int port;
+ if ( d->vcpu[bind->vcpu] == NULL )
+ return -ENOENT;
+
spin_lock(&d->evtchn_lock);
if ( (port = get_free_port(d)) >= 0 )
{
chn = evtchn_from_port(d, port);
chn->state = ECS_IPI;
- chn->notify_vcpu_id = current->vcpu_id;
+ chn->notify_vcpu_id = bind->vcpu;
}
spin_unlock(&d->evtchn_lock);
} evtchn_bind_interdomain_t;
/*
- * EVTCHNOP_bind_virq: Bind a local event channel to IRQ <irq> on calling vcpu.
+ * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
+ * vcpu.
* NOTES:
* 1. A virtual IRQ may be bound to at most one event channel per vcpu.
- * 2. The allocated event channel is bound to the calling vcpu. The binding
+ * 2. The allocated event channel is bound to the specified vcpu. The binding
* may not be changed.
*/
#define EVTCHNOP_bind_virq 1
typedef struct evtchn_bind_virq {
/* IN parameters. */
u32 virq;
+ u32 vcpu;
/* OUT parameters. */
u32 port;
} evtchn_bind_virq_t;
/*
- * EVTCHNOP_bind_pirq: Bind a local event channel to IRQ <irq>.
+ * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ <irq>.
* NOTES:
* 1. A physical IRQ may be bound to at most one event channel per domain.
* 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
/*
* EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
* NOTES:
- * 1. The allocated event channel is bound to the calling vcpu. The binding
+ * 1. The allocated event channel is bound to the specified vcpu. The binding
* may not be changed.
*/
#define EVTCHNOP_bind_ipi 7
typedef struct evtchn_bind_ipi {
+ u32 vcpu;
/* OUT parameters. */
u32 port;
} evtchn_bind_ipi_t;